#include "ParamReader.h"

std::ifstream ParamReader::cfgFile; 

//Experiment	
int			ParamReader::EXP_NUM_RUNS						=1;			//number of trials (for statistical significant)
int			ParamReader::EXP_NUM_EPISODES					=50;		//number of episodes in each run
int			ParamReader::EXP_NUM_STEPS						=300;		//max number of steps in each episode
int			ParamReader::EXP_TYPE							=0;			//type of experiment: (0) planning, (1) offline learning, (2) online learning	


//agent
int			ParamReader::AGNT_TILE_RESOLUTION				=8; 
int			ParamReader::AGNT_NUMBER_OF_TILINGS				=14; 
double		ParamReader::AGNT_EPSILON						=0.1;                    // probability of random action
double		ParamReader::AGNT_BETA							=0.2;
double		ParamReader::AGNT_ALPHA							=0.51;                      // step size parameter
double		ParamReader::AGNT_LAMBDA						=0.9;                     // trace-decay parameters
bool		ParamReader::LOAD_MODEL							=0; 
bool		ParamReader::SAVE_MODEL							=0;


 bool ParamReader::load(const char * fname)
 {
	 try{
	 cfgFile.open(fname); 
	 }
	 catch(...)
	 {
		return false; 
	 }
	 if (! cfgFile.is_open())
		 return false; 

	//experiment
	readInt("EXP_NUM_RUNS",ParamReader::EXP_NUM_RUNS); 
	readInt("EXP_NUM_EPISODES", ParamReader::EXP_NUM_EPISODES); 
	readInt("EXP_NUM_STEPS",ParamReader::EXP_NUM_STEPS); 
	readInt("EXP_TYPE", ParamReader::EXP_TYPE); 



	//agent
	readInt("AGNT_TILE_RESOLUTION",ParamReader::AGNT_TILE_RESOLUTION); 
	readInt("AGNT_NUMBER_OF_TILINGS", ParamReader::AGNT_NUMBER_OF_TILINGS); 
	readDouble("AGNT_EPSILON",ParamReader::AGNT_EPSILON); 
	readDouble("AGNT_BETA",ParamReader::AGNT_BETA); 
	readDouble("AGNT_ALPHA",ParamReader::AGNT_ALPHA); 
	readDouble("AGNT_LAMBDA",ParamReader::AGNT_LAMBDA); 
	readBool("LOAD_MODEL", ParamReader::LOAD_MODEL); 
	readBool("SAVE_MODEL", ParamReader::SAVE_MODEL); 
	
	cfgFile.close(); 
	return true; 
 }

void ParamReader::print()
{
printf("---------params---------------\n"); 
printf("Experiment parameters: \n"); 
	printf("\tEXP_NUM_RUNS\t\t%d \n",ParamReader::EXP_NUM_RUNS ); 
	printf("\tEXP_NUM_EPISODES\t%d \n", ParamReader::EXP_NUM_EPISODES); 
	printf("\tEXP_NUM_STEPS\t\t%d \n",ParamReader::EXP_NUM_STEPS ); 
	printf("\tEXP_TYPE\t\t%d \n", ParamReader::EXP_TYPE); 

printf("Agent params: \n"); 
	printf("\tAGNT_TILE_RESOLUTION\t\t%d \n",ParamReader::AGNT_TILE_RESOLUTION ); 
	printf("\tAGNT_NUMBER_OF_TILINGS\t%d \n", ParamReader::AGNT_NUMBER_OF_TILINGS); 
	printf("\tAGNT_EPSILON\t\t\t%lf \n", AGNT_EPSILON); 
	printf("\tAGNT_BETA\t\t\t%lf \n", AGNT_BETA); 
	printf("\tAGNT_LAMBDA\t\t\t%lf \n", AGNT_LAMBDA); 
	printf("\tAGNT_ALPHA\t\t\t%lf \n", AGNT_ALPHA); 
	printf("\tLOAD_MODEL\t\t\t%d	\n", LOAD_MODEL); 
	printf("\tSAVE_MODEL\t\t\t%d	\n", SAVE_MODEL); 
printf("-------------------------------\n"); 
 }


//! returns true if the (0-terminated) string s contains c 
  inline bool contains(const char* s,char c){
    for(int i=0;s[i];i++) if(s[i]==c) return true;
    return false;
  }

  //! skips the chars (typically white characters) when parsing from the istream
  inline char skip(std::istream& is,char* skipchars){
    char c;
    do{ c=is.get(); } while(contains(skipchars,c));
    is.putback(c);
    return c;
  }



char ParamReader::getNextChar(std::ifstream& cfg)
{
	if (! cfg.good())
		return '\n';

	char c = cfg.get(); 
	if (c == '#') 
	{
		while (cfg.good())
		{
			c = cfg.get(); 
			if (c == '\n')
				return c; 
		}
		return '\n'; 
	}
	return c; 
}


bool ParamReader::skip2param(const char* tag)
{
	cfgFile.clear();
	cfgFile.seekg(std::ios::beg);
	if(!cfgFile.good()) return false;

	unsigned n=strlen(tag);
	char *buf=new char [n+2]; memset(buf,0,n+2);
	while(cfgFile.good()){
		memmove(buf,buf+1,n);
		buf[n]=getNextChar(cfgFile); 

		if (buf[n] =='#') 
			skip(cfgFile,"\n"); 
		if(buf[n]==' ' || buf[n]=='\t' || buf[n]==':' || buf[n]=='=')
		{ 
			buf[n]=0; 
			if(!strcmp(tag,buf)) 
				break; 
			buf[n]=':'; 
		}
	};
	delete[] buf;

	if(!cfgFile.good()) return false;

	skip(cfgFile," :=\n\r\t");

	return true; 
}

int ParamReader::readInt(const char* tag, int& value)
{

	if (skip2param(tag))
		cfgFile >>value;

	return value; 
}


double ParamReader::readDouble(const char* tag, double& value)
{

	if (skip2param(tag))
		cfgFile >>value;

	return value; 
}


char* ParamReader::readString(const char* tag, char*& value)
{

	if (skip2param(tag))
	cfgFile >>value;

	return value; 
}

bool ParamReader::readBool(const char* tag, bool& value)
{

	if (skip2param(tag))
		cfgFile >>value;

	return value; 
}

